/*
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 * http://www.gnu.org/licenses/gpl-3.0.html
 */

/*信息面板管理*/
#ifndef INFOPANE_H
#define INFOPANE_H


#include <limits>
#include <logmanager.h>

#include "cbauibook.h"

static const int infopane_flags = wxAUI_NB_MIDDLE_CLICK_CLOSE
                                | wxAUI_NB_WINDOWLIST_BUTTON
                                | wxAUI_NB_SCROLL_BUTTONS
                                | wxAUI_NB_TAB_MOVE
                                | wxAUI_NB_TAB_SPLIT;

class wxWindow;
class wxCommandEvent;
class wxMouseEvent;

class InfoPane : public cbAuiNotebook
{
    DECLARE_EVENT_TABLE()

    struct Page
    {
        Page() : icon(nullptr), window(nullptr), logger(nullptr), indexInNB(std::numeric_limits<int>::min()), eventID(0), islogger(0) {};
        wxString  title;
        wxBitmap* icon;
        wxWindow* window;
        Logger*   logger;
        // used to be "visible" flag: invisible is <0, any other value means visible
        // 用于"可见(visible)"标志:不可见小于0,任何其他值表示可见
        int       indexInNB;
        int       eventID;
        bool      islogger;
    };

    typedef int (*CompareFunction)(Page**, Page**);
    static int  CompareIndexes(Page **p1, Page **p2);
    void        ReorderTabs(CompareFunction cmp_f);

    wxBitmap m_DefaultBitmap;

    WX_DEFINE_ARRAY(Page*, wxArrayOfPage);
    wxArrayOfPage m_Pages;

    void Toggle(size_t index);
    void Hide(size_t i);

    void OnMenu(wxCommandEvent& event);
    void OnCopy(wxCommandEvent& event);
    void OnWrapMode(wxCommandEvent& event);
    void OnClear(wxCommandEvent& event);
    void ContextMenu(wxContextMenuEvent& event);
    void OnTabContextMenu(wxAuiNotebookEvent& event);
    void OnCloseClicked(wxAuiNotebookEvent& event);
    void OnTabPosition(wxCommandEvent& event);
    void DoShowContextMenu();
    int  AddPagePrivate(wxWindow* p, const wxString& title, wxBitmap* icon = nullptr);
    bool InsertPagePrivate(wxWindow* p, const wxString& title, wxBitmap* icon = nullptr, int index = -1);
    using wxWindow::Show;
public:

    InfoPane(wxWindow* parent);
    virtual ~InfoPane();

    /*
    *  Show a tab, or bring it to the foreground if already shown.
    *  Only use this method if crucial information is shown which the user must not miss, or if
    *  information is shown that requires input from the user (for example search results).
    *  In all other cases, it is the user's decision which tab he wants to look at, not yours.
    *  Note that you cannot hide a tab programatically.
     *
     * 显示选项卡,如果已显示,则将其置于前台.
     * 只有在显示了用户不能错过的关键信息,或者显示了需要用户输入的信息(例如搜索结果)时,才使用此方法.
     * 在所有其他情况下,用户决定要查看哪个选项卡,而不是您的选项卡.
     * 请注意,不能以编程方式隐藏选项卡.
    */
    void Show(size_t index);
    void Show(Logger* logger);
    void Hide(Logger* logger);
    void ShowNonLogger(wxWindow* p);
    void HideNonLogger(wxWindow* p);

    int GetPageIndexByWindow(wxWindow* win);
    int GetCurrentPage(bool &is_logger);

    Logger*   GetLogger(int index);
    wxWindow* GetWindow(int index);

    // refreshes the tab effective order, needed, because tabs might have moved with drag and drop
    // 刷新选项卡所需的有效顺序,因为选项卡可能已随拖放一起移动
    void UpdateEffectiveTabOrder();
    void LoadTabOrder(wxString layout);
    wxString SaveTabOrder();

    /*
    *  You should not need to call these functions under normal conditions. The application initialises
    *  everything at startup, after the main window has been created and the plugins have been loaded.
    *  AddLogger:
    *  Add the GUI control obtained by a logger's CreateControl() function.
    *  DeleteLogger:
    *  Remove (delete) a tab and its logger. All log output directed to the corresponding log index
    *  will be redirected to the null log thereafter.
    *  To prove that you are serious, you must know the logger belonging to the tab to delete.
     *
     *  在正常情况下不需要调用这些函数.在创建主窗口并加载插件之后,应用程序在启动时初始化所有内容.
     *  添加日志管理器(AddLogger):
     *  添加由记录器的CreateControl()函数获取的GUI控件.
     *  删除日志管理器(DeleteLogger):
     *  移除(删除)选项卡及其记录器.所有指向相应日志索引的日志输出都将被重定向到空日志.
     *  要证明您是认真的,您必须知道属于要删除的选项卡的记录器.
     *
    */
    bool AddLogger(Logger* logger, wxWindow* p, const wxString& title, wxBitmap* icon = nullptr);
    bool DeleteLogger(Logger* l);

    /*
    *  If something that is not a logger should be placed in the info pane (think twice about this before doing it),
    *  use AddNonLogger()/DeleteNonLogger() for that purpose.
    *  An example of something that is not a logger but might still show up in the info pane is the list of search results.
     *
     *  如果某个不是记录器的内容应该放在"信息"窗格中(在执行此操作之前请三思),请为此目的使用AddNonLogger()/DeleteNonLogger().
     *  搜索结果列表是一个例子,它不是一个记录器,但可能仍然显示在"信息"窗格中.
    */
    bool AddNonLogger(wxWindow* p, const wxString& title, wxBitmap* icon = nullptr);
    bool RemoveNonLogger(wxWindow* p);
    bool DeleteNonLogger(wxWindow* p);
};


#endif
